<template>
  <div class="xtx-numbox">
    <div class="label" v-if="isLabel">数量</div>
    <div class="numbox">
      <a href="javascript:;" @click="ins">-</a>
      <input type="text" readonly :value="num" />
      <a href="javascript:;" @click="add">+</a>
    </div>
  </div>
</template>

<script>
/**
 * 1. 增减逻辑
 *    思路: 准备一个响应式数据 点击增减按钮操作这个数据 把这个数据绑定到value
 *
 * 2. 通过父传子控制最大值和最小值
 *    思路：通过父传子传入最大值和最小值 + 判断逻辑
 *
 * 3. 实现组件的v-model双向绑定
 *    回顾：v-model如果写到了一个组件身上相当于做了哪些事儿？
 *    vue2.x
 *     <Foo v-model="num"/>
 *     1. 给Foo组件默认绑定了一个名称为value的属性 <Foo :value="num"/>
 *     2. 给Foo组件默认绑定了一个名称为input的自定义事件 <Foo @input="inputHandler"/>
 *     3. 在Foo组件内部如果你通过$emit方法触发这个input事件 触发事件时传递的参数
 *        会自动绑定到num的身上
 *        $emit('input', '这是数据') -> num = '这是数据'
 *
 *    vue3.x
 *     <Foo v-model="num"/>
 *    1. 给Foo组件默认绑定了一个名称为modelValue的属性 <Foo :model-value="num"/>
 *    2. 给Foo组件默认绑定了一个名称为update:modelValue的自定义事件 <Foo @update:modelValue="inputHandler"/>
 *    3. 在Foo组件内部如果你通过$emit方法触发这个update:modelValue事件 触发事件时传递的参数
 *        会自动绑定到num的身上
 *        $emit('update:modelValue', '这是数据') -> num = '这是数据'
 *
 *   效果描述：
 *    1. checkNumber组件input的value到底显示啥由父组件决定 v-model="num"  父->子
 *
 *       初始化要以父为主  const num = ref(props.modelValue)
 *       父传入的值发生变化 组件内部要以父为主  watch
 *
 *    2. 当在checkNumber组件中通过增减按钮修改数据的时候 需要通知父组件 让v-model绑定的数据是最新的 子->父
 *
 *       在子组件内部 如果数据发生变化 手动通过emit方法触发事件
 *       并把当前最新的数据通过自定义事件传递出去即可
 *
 *  封装v-model组件的套路
 *
 *   1. 父传子
 *      const num = ref(props.modelValue) 初始同步
 *      watch(()=>props.modelValue, ()=> num.value = props.modelValue) 再次同步
 *
 *   2. 子传父
 *      emit('update:modelValue', '子组件中最新的数据')
 */
import { ref, watch } from 'vue'
export default {
  name: 'XtxNumBox',
  props: {
    max: {
      type: Number
    },
    min: {
      type: Number
    },
    // 接收数据
    modelValue: {
      type: Number
    },
    // 是否显示label
    isLabel: {
      type: Boolean,
      default: true
    }
  },
  setup (props, { emit }) {
    // 通过v-model传入的值只能更新到props的位置
    // 并不能自动同步到num
    // 如何解决父组件数据已经变化 但是子组件并没有更新的问题？
    // 思路：当我们知道modelValue变化了 就立刻进行重新同步数据
    const num = ref(props.modelValue)
    watch(() => {
      return props.modelValue
    }, () => {
      // 立刻进行同步修改
      num.value = props.modelValue
    })
    // 加逻辑
    function add () {
      if (props.max === num.value) {
        return
      }
      num.value++
      // 同步到父组件中
      emit('update:modelValue', num.value)
      // 增加change
      emit('change', num.value)
    }
    function ins () {
      if (props.min === num.value) {
        return
      }
      num.value--
      // 同步到父组件中
      emit('update:modelValue', num.value)
      // 增加change
      emit('change', num.value)
    }
    // 减逻辑
    return {
      num, add, ins
    }
  }
}
</script>
<style scoped lang="less">
.xtx-numbox {
  display: flex;
  align-items: center;
  .label {
    width: 60px;
    color: #999;
    padding-left: 10px;
  }
  .numbox {
    width: 120px;
    height: 30px;
    border: 1px solid #e4e4e4;
    display: flex;
    > a {
      width: 29px;
      line-height: 28px;
      text-align: center;
      background: #f8f8f8;
      font-size: 16px;
      color: #666;
      &:first-of-type {
        border-right: 1px solid #e4e4e4;
      }
      &:last-of-type {
        border-left: 1px solid #e4e4e4;
      }
    }
    > input {
      width: 60px;
      padding: 0 5px;
      text-align: center;
      color: #666;
    }
  }
}
</style>
